﻿using UnityEngine;
using System.Collections;

//------------------------------------------------------------
// shaco Framework
// Copyright © 2017-2021 chang.liu All rights reserved.
// Feedback: 449612236@qq.com
//------------------------------------------------------------

namespace shaco
{
    public class Repeat : ActionBase
    {
        public delegate void SS_CallFUNC_LOOP_COMPLETE(int loop);

        public SS_CallFUNC_LOOP_COMPLETE onLoopCompleteFunc = null;

        protected ActionBase _actionTarget;
        protected int _iLoop = 1;
        protected int _iCurrentTimes = 1;

        static public Repeat Create(ActionBase action, int loop)
        {
            var ret = shaco.GameHelper.objectpool.Instantiate(() => new Repeat());
            ret._actionTarget = action;
            ret._iLoop = loop;
            action.StopMe();
            ret.AddActionTargetCompletedCallBack(action);
            return ret;
        }

        static public Repeat CreateRepeatForever(ActionBase action)
        {
            var ret = shaco.GameHelper.objectpool.Instantiate(() => new Repeat());
            ret._actionTarget = action;
            ret._iLoop = -1;
            action.StopMe();
            ret.AddActionTargetCompletedCallBack(action);
            return ret;
        }

        public override void OnReset()
        {
            base.OnReset();

            if (null != _actionTarget)
                _actionTarget.OnReset();

            this.onLoopCompleteFunc = null;
            this._actionTarget = null;
            this._iCurrentTimes = 1;
            this._iLoop = 1;

            if (shaco.GameHelper.objectpool.IsInstantiated(this))
                this.RecyclingWithPool();
        }

        public override void RunAction(GameObject target)
        {
            if (_actionTarget != null)
                _actionTarget.RunActionWithoutPlay(target);
            base.RunAction(target);
        }

        public override float UpdateAction(float prePercent)
        {
            if (!this.IsActionAlive())
            {
                _actionTarget.onCompleteFunc -= OnTargetCompletedCallBack;
                return base.UpdateAction(prePercent);
            }

            SetActionAlive(true);
            prePercent = _actionTarget.GetCurrentPercent();

            //当无限循环的时候，需要在UpdateAction前重新设置prePercent，否则在一帧等待时间太长的时候，会导致自动AddRemove销毁了无限循环动作
            if (_iLoop < 0)
            {
                prePercent = 0;
            }

            if (_actionTarget != null)
            {
                prePercent = _actionTarget.GetCurrentPercent();
                _actionTarget.UpdateAction(prePercent);
            }

            return base.UpdateAction(prePercent);
        }

        public override ActionBase Clone()
        {
            return Repeat.Create(_actionTarget, _iLoop);
        }

        public override ActionBase Reverse(GameObject target)
        {
            return Repeat.Create(_actionTarget, _iLoop);
        }

        public override void PlayEndDirectly()
        {
            if (_actionTarget != null)
            {
                _actionTarget.PlayEndDirectly();
            }
            base.PlayEndDirectly();
        }

        public override void Reset(bool isContinuePlay)
        {
            base.Reset(isContinuePlay);

            _iCurrentTimes = 1;

            if (_actionTarget != null)
            {
                _actionTarget.Reset(isContinuePlay);
            }
        }

        public int GetCurrentLoop()
        {
            return _iCurrentTimes;
        }

        public void SetActionTarget(ActionBase action)
        {
            _actionTarget = action;
        }

        public ActionBase GetActionTarget()
        {
            return _actionTarget;
        }

        private void AddActionTargetCompletedCallBack(ActionBase target)
        {
            target.onCompleteFunc -= OnTargetCompletedCallBack;
            target.onCompleteFunc += OnTargetCompletedCallBack;
        }

        private void OnTargetCompletedCallBack(ActionBase action)
        {
            if (_iCurrentTimes < _iLoop || _iLoop < 0)
            {
                if (onLoopCompleteFunc != null)
                    onLoopCompleteFunc(_iCurrentTimes);

                _actionTarget.RunActionWithoutPlay(_actionTarget.target);
                this.SetActionAlive(true);
            }
            else
            {
                _actionTarget.onCompleteFunc -= OnTargetCompletedCallBack;
                SetActionAlive(false);
            }
                
            if (_iCurrentTimes > int.MaxValue - 1)
                _iCurrentTimes = 0;
            else
                ++_iCurrentTimes;
        }

        private Repeat() { }
    }
}